﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading;
using HJ212_Common;
using HJ212_Protocol;
using HJT212_Protocol_DAL.DAO;
using HJT212_Protocol_DAL.Model;
using SailHero.Soft.ESB.Communication.ClientAndServer.Communication.EndPoints.Tcp;
using SailHero.Soft.ESB.Communication.ClientAndServer.Communication.Messages;
using SailHero.Soft.ESB.Communication.ClientAndServer.Server;
using Message = HJ212_Protocol.Message;

namespace HJT212_Protocol_Server
{
    public class HostProtocolServer
    {
        #region 字段属性
        public IServer server;
        public bool IsHandleOffLine = ConfigOprater.GetNodeValue("IsHandleOffLine") == "1";

        public CommunicationServer ComuSrv { get; set; }

        /// <summary>
        /// 服务是否正在运行状态
        /// </summary>
        public bool IsRuning
        {

            get
            {
                if (server == null)
                {
                    return false;
                }
                else
                {
                    return server.IsRuning();
                }
            }
        }

        private const string pingQN = "20000000000000001";

        private log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        private int MaxConnNum = Convert.ToInt32(ConfigOprater.GetNodeValue("MaxConnNum"));



        #endregion

        #region 事件
        private void server_ClientConnected(object sender, ServerClientEventArgs e)
        {

            try
            {
                #region 判断是否超过最大连接数
                if (server.Clients.Count > MaxConnNum)
                {
                    ComuSrv.showHostTraceMsg("服务超出设置的最大连接数，强制剔除新进链接:" + e.Client.ClientSocket.RemoteEndPoint);
                    e.Client.Disconnect();
                    return;
                }
                #endregion

                e.Client.MN = "XHHB" + DateTime.Now.ToString("yyyyMMddHHmmssfff");
                ///todo:需要考虑上位机的连通性测试问题，
                /// 解决问题的办法就是提供给需要使用的系统DLL做二次开发
                e.Client.StopPing(3);
                e.Client.MessageReceived += Client_MessageReceived;
                ShowClients(e.Client);
            }
            catch (Exception ex)
            {
                log.Error("出现异常", ex);
            }
        }
        /// <summary>
        /// 清理客户端列表，默认2小时清理一次
        /// </summary>
        /// <param name="hours">清理的时间间隔</param>
        public void CleanNoUsedClient(int hours)
        {
            try
            {
                if (hours <= 0) return;
                hours = 2;
                List<IServerClient> lstClents = server.Clients.GetAllItems();
                var lst = lstClents.Where(itm =>
                                             (itm.LastReceivedMessageTime - DateTime.Now).Hours > hours
                                             && (itm.LastSentMessageTime - DateTime.Now).Hours > hours);

                if (lst != null && lst.Count() > 0)
                {
                    List<IServerClient> lstClnts = lst.ToList();

                    lstClnts.ForEach(itm =>
                                         {
                                             try
                                             {
                                                 itm.Disconnect();
                                             }
                                             catch (Exception ex)
                                             {
                                                 log.Error("出现异常", ex);
                                             }
                                         });
                }
                ///todo:定时清理MessageCache表中的数据 比如说清理大于当前时间2小时的数据
            }
            catch (Exception ex)
            {
                log.Error("出现异常", ex);
            }
        }



        private void server_ClientDisconnected(object sender, ServerClientEventArgs e)
        {
            ParameterizedThreadStart Start = new ParameterizedThreadStart(o => ShowOnlineClients());
            Thread Thrd = new Thread(Start);
            Thrd.Start();
        }
        private void Client_MessageReceived(object sender, MessageEventArgs e)
        {
            try
            {
                IServerClient srvclnt = (IServerClient)sender;
                ParameterizedThreadStart Start = new ParameterizedThreadStart(o => MsgReceived(srvclnt, e.Message));
                Thread Thrd = new Thread(Start);
                Thrd.Start();
            }
            catch (Exception ex)
            {
                log.Error("出现异常", ex);
                //throw;
            }

        }
        #endregion

        #region 方法函数

        #region 公有

        /// <summary>
        /// 初始化
        /// </summary>
        private void Init()
        {
            try
            {
                string _port = ConfigOprater.GetNodeValue("HostSrvPort");
                server = ServerFactory.CreateServer(new ESBTcpEndPoint(Convert.ToInt32(_port)));

                server.WireProtocolFactory = new MyWireProtocolFactory(); //自定义通讯协议工厂!
                server.ClientConnected += server_ClientConnected;
                server.ClientDisconnected += server_ClientDisconnected;

                UpdateOffLineAll();

            }
            catch (Exception ex)
            {
                log.Error("出现异常", ex);
            }
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public void Init(CommunicationServer cmSrv)
        {
            try
            {
                Init();
                ComuSrv = cmSrv;
                cmSrv.HostSrv = this;
            }
            catch (Exception ex)
            {
                log.Error("出现异常", ex);
            }
        }
        /// <summary>
        /// 停止
        /// </summary>
        public void Stop()
        {
            try
            {
                if (IsRuning)
                {
                    UpdateOffLineAll();
                    server.Stop();
                }

            }
            catch (Exception ex)
            {

                log.Error("出现异常", ex);
            }
        }


        /// <summary>
        /// 停止
        /// </summary>
        public void Start()
        {
            try
            {
                if (!IsRuning)
                {
                    (new Thread(new ThreadStart(server.Start))).Start();
                }
            }
            catch (Exception ex)
            {

                log.Error("出现异常", ex);
            }
        }


        #endregion


        #region 私有

        public void UpdateOffLineAll()
        {
            try
            {
                HostClientDao HclntDao = new HostClientDao();
                HclntDao.UpdateAllOffOnline();
            }
            catch (Exception ex)
            {

                log.Error("出现异常", ex);
            }
        }

        private void MsgReceived(IServerClient clent, IMessage Msg)
        {
            try
            {
                TextMessage Tmsg = (TextMessage)Msg;

                #region 记录
                string fromMN = clent.MN;
                string toMN = Tmsg.MN;
                MsgCacheDao msgcacheDao = new MsgCacheDao();
                TB_MESSAGECACHELISTModel cachemdl = new TB_MESSAGECACHELISTModel() { MessageID = Tmsg.MessageId, MN = fromMN };
                msgcacheDao.InsertToCache(Tmsg.Text, cachemdl);
                #region 显示跟踪信息
                if (Tmsg.QN != pingQN && ComuSrv.showHostTraceMsg != null)
                {
                    string msg = "From({0}):{1}";
                    msg = string.Format(msg, clent.ClientSocket.RemoteEndPoint, Tmsg.Text);
                    ComuSrv.showHostTraceMsg(msg);
                }
                #endregion

                #endregion

                #region 转发
                var lstSClients = ComuSrv.ClntSrv.server.Clients.GetAllItems().Where(
                    delegate(IServerClient itm)
                    {
                        return itm.MN == toMN;
                    });
                if (lstSClients != null && lstSClients.Count() > 0)
                {
                    IServerClient itm = lstSClients.First();
                    ComuSrv.ClntSrv.SendMessage(itm, Tmsg);

                }
                else///todo:不在线的缓存处理 写入send缓存表
                {
                    CMD_SendModel mdl = ComuSrv.ConvertToMdlFromMsg(Tmsg);
                    if (mdl != null)
                    {
                        CMD_SendDao sendDao = new CMD_SendDao();
                        sendDao.AddCMDToCache(mdl);
                    }
                }
                #endregion

            }
            catch (Exception ex)
            {

                log.Error("出现异常", ex);
            }
        }

        /// <summary>
        /// 显示客户端列表数据至列表控件
        /// </summary>
        /// <param name="clients">客户端列表</param>
        private void ShowClients(IServerClient srvClient)
        {

            try
            {
                if (srvClient == null) return;
                ShowOnlineClients();
            }
            catch (Exception ex)
            {

                log.Error("出现异常", ex);
            }
        }

        /// <summary>
        /// 显示所有在线的客户端
        /// </summary>
        private void ShowOnlineClients()
        {
            try
            {

                if (ComuSrv != null && ComuSrv.showHostOnlineEndPoints != null)
                {
                    List<string> lstEndPoints = new List<string>();
                    if (server.Clients.Count > 0)
                    {


                        var lst =
                            server.Clients.GetAllItems().Select(itm =>
                                                                    {
                                                                        string RemoteEndPoint = "";
                                                                        try
                                                                        {
                                                                            RemoteEndPoint =
                                                                                itm.ClientSocket.RemoteEndPoint.ToString
                                                                                    ();
                                                                        }
                                                                        catch (Exception ex)
                                                                        {
                                                                            log.Error("出现异常", ex);
                                                                            server.Clients.Remove(itm.ClientId);
                                                                        }

                                                                        return RemoteEndPoint;
                                                                    });

                        if (lst != null && lst.Count() > 0)
                        {
                            lst = lst.Where(itm => !string.IsNullOrEmpty(itm));
                            if (lst != null && lst.Count() > 0)
                            {
                                lstEndPoints = lst.ToList();
                            }
                        }
                    }
                    ComuSrv.showHostOnlineEndPoints(lstEndPoints);
                }
            }
            catch (Exception ex)
            {
                log.Error("出现异常", ex);
            }
        }


        private TextMessage ConvertTomsgFromMdl(CMD_SendModel mdl)
        {
            if (mdl == null) return null;
            try
            {
                string cmd = "";
                if (mdl.QN != null)
                {
                    cmd = cmd + "QN=" + mdl.QN + ";";
                }
                if (mdl.ST != null)
                {
                    cmd = cmd + "ST=" + mdl.ST + ";";
                }
                if (mdl.MN != null)
                {
                    cmd = cmd + "MN=" + mdl.MN + ";";
                }
                if (mdl.CN != null)
                {
                    cmd = cmd + "CN=" + mdl.CN + ";";
                }
                if (mdl.PW != null)
                {
                    cmd = cmd + "PW=" + mdl.PW + ";";
                }
                if (mdl.CP != null)
                {
                    cmd = cmd + "CP=&&" + mdl.QN + "&&";
                }
                TextMessage msg = new TextMessage(cmd);
                return msg;

            }
            catch (Exception ex)
            {

                log.Error("出现异常", ex);
            }

            return null;
        }


        #endregion


        #endregion
    }
}
